package com.dongbing.support.executor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.dongbing.entity.base.BaseEntity;
import com.dongbing.entity.support.BatchTaskDetailPO;
import com.dongbing.enums.BatchTaskBizType;
import com.dongbing.enums.BatchTaskDetailState;
import com.dongbing.support.CollectBeanPostProcessor;
import com.dongbing.support.context.BatchTaskContext;
import com.dongbing.support.result.TaskExecuteResult;
import com.dongbing.support.service.BatchTaskDetailService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.istack.internal.NotNull;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 批量任务执行器顶级父类
 * @param <T> 实体类
 */
@Slf4j
public abstract class BatchTaskExecutor<T extends BaseEntity> {

    @Resource
    private BatchTaskDetailService batchTaskDetailService;

    @Resource
    private ObjectMapper objectMapper;

    /**
     * 批量任务类型(定位执行器)
     * @return 批量任务执行类型
     */
    public abstract BatchTaskBizType type();

    /**
     * 批量任务执行实体类类型
     * @return Class
     */
    public abstract Class<T> entityClass();

    /**
     * 批量任务执行
     * @param data 批量任务执行数据
     * @throws Exception 异常
     */
    public abstract void execute(@NotNull T data) throws Exception;

    @SuppressWarnings("all")
    public List<TaskExecuteResult<T>> doExecute(BatchTaskBizType bizType, @NotNull List<T> list) {
        List<TaskExecuteResult<T>> results = new ArrayList<>();
        list = CollectBeanPostProcessor.getLoader(bizType).enrichData(list);
        if (!list.isEmpty()) {
            for (T data : list) {
                BatchTaskDetailPO batchTaskDetailPO = null;
                if (Objects.nonNull(data.getId())) {
                    batchTaskDetailPO = batchTaskDetailService.getOne(new LambdaQueryWrapper<BatchTaskDetailPO>()
                            .eq(BatchTaskDetailPO::getBatchTaskId, BatchTaskContext.get().getId())
                            .eq(BatchTaskDetailPO::getDataId, data.getId())
                    );
                    if (Objects.nonNull(batchTaskDetailPO) && !BatchTaskDetailState.INIT.equals(batchTaskDetailPO.getState())) {
                        try {
                            log.warn("[批量任务]批量任务已执行完成,数据记录:{}", objectMapper.writeValueAsString(data));
                        } catch (JsonProcessingException e) {
                            throw new RuntimeException(e);
                        }
                        continue;
                    }
                }
                TaskExecuteResult<T> result = new TaskExecuteResult<>();
                result.setData(data);
                result.setBatchTaskDetailPO(batchTaskDetailPO);
                try {
                    execute(data);
                    result.setSuccess(Boolean.TRUE);
                } catch (Exception e) {
                    result.setSuccess(Boolean.FALSE);
                    result.setErrMsg(StringUtils.isNotBlank(e.getMessage()) ? e.getMessage() : "操作失败");
                } finally {
                    results.add(result);
                }
            }
        }
        return results;
    }

    @SuppressWarnings("all")
    public static List<TaskExecuteResult<Object>> batchExecute(@NotNull BatchTaskBizType bizType, @NotNull List<Object> datas) {
        return CollectBeanPostProcessor.getExecutor(bizType).doExecute(bizType, datas);
    }


}
